package com.liuyjy.base.common.util;


import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Author liuyjy
 * @Date 2025/1/9 13:24
 * @Description: AES 加密解密工具类
 **/
public class AESUtil {
    public static final String KEY_CODE = "liuyjyKey@#$!216";
    public static final String ID_KEY_CODE = "liuyjyKey@#$!218";
    private final static String AES = "AES";
    private final static String ENCRYPT_TYPE = "AES/ECB/PKCS5Padding";
    private static Log log = LogFactory.getLog(AESUtil.class);

    /**
     * 加密
     *
     * @param sSrc 字符串
     * @param sKey 密码
     * @return String
     */
    public static String encrypt(String sSrc, String sKey) {
        if (EmptyUtil.isEmpty(sSrc)) {
            return sSrc;
        }
        // 判断Key是否正确
        if (EmptyUtil.isEmpty(sKey)) {
            log.info("Key为空null");
            return null;
        }
        // 判断Key是否为16位
        if (sKey.length() != 16) {
            log.info("Key长度不是16位");
            return null;
        }
        try {
            byte[] raw = sKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
            // "算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance(ENCRYPT_TYPE);
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] srbts = sSrc.getBytes(StandardCharsets.UTF_8);
            byte[] encrypted = cipher.doFinal(srbts);
            // 此处使用BASE64做转码功能，同时能起到2次加密的作用。
            return new Base64().encodeToString(encrypted);
        } catch (Exception e) {
            log.error("加密过程中发生异常", e);
            return null;
        }
    }

    /**
     * id 加密
     *
     * @param id id
     * @return String
     */
    public static String encryptById(Object id) {
        if (EmptyUtil.isEmpty(id)) {
            return null;
        }
        if (id instanceof Long) {
            return encryptById(id.toString());
        }
        if (id instanceof Integer) {
            return encryptById(id.toString());
        }
        return id.toString();
    }

    /**
     * id 加密
     *
     * @param sSrcList id
     * @return Set<String>
     */
    public static Set<String> encryptByIdSet(Set<Long> sSrcList) {
        if (EmptyUtil.isEmpty(sSrcList)) {
            return null;
        }
        Set<String> idList = new HashSet<>();
        for (Long id : sSrcList) {
            idList.add(encryptById(id.toString()));
        }
        return idList;
    }

    /**
     * id 加密
     *
     * @param sSrcList id
     * @return List<String>
     */
    public static List<String> encryptByIdList(List<Long> sSrcList) {
        if (EmptyUtil.isEmpty(sSrcList)) {
            return null;
        }
        List<String> idList = new ArrayList<>();
        for (Long id : sSrcList) {
            idList.add(encryptById(id.toString()));
        }
        return idList;
    }

    /**
     * id 加密
     *
     * @param sSrcList id
     * @return Set<String>
     */
    public static Set<String> encryptById(Set<Object> sSrcList) {
        if (EmptyUtil.isEmpty(sSrcList)) {
            return null;
        }
        Set<String> idList = new HashSet<>();
        for (Object id : sSrcList) {
            if (id instanceof Long) {
                idList.add(encryptById(id.toString()));
                continue;
            }
            if (id instanceof Integer) {
                idList.add(encryptById(id.toString()));
                continue;
            }
            idList.add(id.toString());
        }
        return idList;
    }

    /**
     * id 加密
     *
     * @param sSrcList id
     * @return List<String>
     */
    public static List<String> encryptById(List<Object> sSrcList) {
        if (EmptyUtil.isEmpty(sSrcList)) {
            return null;
        }
        List<String> idList = new ArrayList<>();
        for (Object id : sSrcList) {
            if (id instanceof Long) {
                idList.add(encryptById(id.toString()));
                continue;
            }
            if (id instanceof Integer) {
                idList.add(encryptById(id.toString()));
                continue;
            }
            idList.add(id.toString());
        }
        return idList;
    }

    /**
     * id 加密
     *
     * @param id id
     * @return String
     */
    public static String encryptById(Long id) {
        if (EmptyUtil.isEmpty(id)) {
            return null;
        }
        return encryptById(String.valueOf(id));
    }

    /**
     * id 加密
     *
     * @param id id
     * @return String
     */
    public static String encryptById(String id) {
        return encrypt(id, ID_KEY_CODE);
    }

    /**
     * id 解密
     *
     * @param sSrcList id
     * @return Set<Long>
     */
    public static Set<Long> decryptById(Set<Object> sSrcList) {
        if (EmptyUtil.isEmpty(sSrcList)) {
            return null;
        }
        Set<Long> idList = new HashSet<>();
        for (Object sSrc : sSrcList) {
            if (sSrc instanceof String) {
                idList.add(decryptById(sSrc.toString()));
                continue;
            }
            idList.add(Long.parseLong(sSrc.toString()));
        }
        return idList;
    }

    /**
     * id 解密
     *
     * @param sSrcList id
     * @return List<Long>
     */
    public static List<Long> decryptById(List<Object> sSrcList) {
        if (EmptyUtil.isEmpty(sSrcList)) {
            return null;
        }
        List<Long> idList = new ArrayList<>();
        for (Object sSrc : sSrcList) {
            if (sSrc instanceof String) {
                idList.add(decryptById(sSrc.toString()));
                continue;
            }
            idList.add(Long.parseLong(sSrc.toString()));
        }
        return idList;
    }

    /**
     * id 解密
     *
     * @param sSrcList id
     * @return Set<Long>
     */
    public static Set<Long> decryptByIdSet(Set<String> sSrcList) {
        if (EmptyUtil.isEmpty(sSrcList)) {
            return null;
        }
        Set<Long> idList = new HashSet<>();
        for (String sSrc : sSrcList) {
            idList.add(decryptById(sSrc));
        }
        return idList;
    }

    /**
     * id 解密
     *
     * @param sSrcList id
     * @return List<Long>
     */
    public static List<Long> decryptByIdList(List<String> sSrcList) {
        if (EmptyUtil.isEmpty(sSrcList)) {
            return null;
        }
        List<Long> idList = new ArrayList<>();
        for (String sSrc : sSrcList) {
            idList.add(decryptById(sSrc));
        }
        return idList;
    }

    /**
     * id 解密
     *
     * @param sSrc id
     * @return Long
     */
    public static Long decryptById(Object sSrc) {
        if (EmptyUtil.isEmpty(sSrc)) {
            return null;
        }
        if (sSrc instanceof String) {
            return decryptById(sSrc.toString());
        }
        return Long.parseLong(sSrc.toString());
    }

    /**
     * id 解密
     *
     * @param sSrc id
     * @return Long
     */
    public static Long decryptById(String sSrc) {
        if (EmptyUtil.isEmpty(sSrc)) {
            return null;
        }
        String decrypt = decrypt(sSrc, ID_KEY_CODE);
        if (EmptyUtil.isEmpty(decrypt)) {
            return Long.valueOf(sSrc);
        }
        if (EmptyUtil.isEmpty(decrypt)) {
            return null;
        }
        return Long.valueOf(decrypt);
    }


    /**
     * 解密
     *
     * @param sSrc 字符串
     * @param sKey 密码
     * @return String
     */
    public static String decrypt(String sSrc, String sKey) {
        if (EmptyUtil.isEmpty(sSrc)) {
            return null;
        }
        // 判断Key是否正确
        if (sKey == null) {
            log.info("Key为空null");
            return null;
        }
        // 判断Key是否为16位
        if (sKey.length() != 16) {
            log.info("Key长度不是16位");
            return null;
        }
        try {
            byte[] raw = sKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
            Cipher cipher = Cipher.getInstance(ENCRYPT_TYPE);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            // 先用base64解密
            byte[] encrypted1 = new Base64().decode(sSrc);
            try {
                byte[] original = cipher.doFinal(encrypted1);
                return new String(original, StandardCharsets.UTF_8);
            } catch (Exception e) {
                log.error("解密过程中发生异常", e);
                return null;
            }
        } catch (Exception ex) {
            log.error("解密过程中发生异常", ex);
            return null;
        }
    }
//    public static void main(String[] args) {
//        String key="1234567";
//        String hmac = Md5Util.getHMAC(key, "DGQCCC");
//        System.out.println(hmac);
//
//    }

    public static void main(String[] args) throws Exception {
        System.out.println(encryptById("U2FsdGVkX18moY0k0gIkvFqkb4nxS4CLih6GOwyOsfg="));
        //21847751 翁娜
        System.out.println("解密==" + decrypt("0RGG0oEgh1EBxgAIj+q60VweswZDivq3rLQ8wSAP11cOXG5qIYCLyGIWtVBQjv42s8tLn9kfxqlMgmC9X1Kgzg==", "syztonKey@#$!216"));

        //System.out.println(decryptById("k+peADDzSO/m/vYaX4egeA=="));

        String decryptPwd = decrypt("123456", "liuyjyKey@#$!216");
        System.out.println("decryptPwd=====" + decryptPwd);


//        com.baomidou.mybatisplus.core.toolkit.AES.encrypt("123456","liuyjyKey@#$!216");
//        System.out.println(com.baomidou.mybatisplus.core.toolkit.AES.encrypt("123456","liuyjyKey@#$!216"));
//        Aes
    }
}
